# Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
# This source file is part of the Cangjie project, licensed under Apache-2.0
# with Runtime Library Exception.
#
# See https://cangjie-lang.cn/pages/LICENSE for license information.

from os import path
import textwrap

dir = path.dirname(path.realpath(__file__))
path = dir + '/test_' + path.basename(dir) + '_{}.cj'
template = '''
/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
 * This source file is part of the Cangjie project, licensed under Apache-2.0
 * with Runtime Library Exception.
 *
 * See https://cangjie-lang.cn/pages/LICENSE for license information.
 */

/*
  @Assertion:   6.1.2.2(3)
                The syntax of the static initializer is as follows.
                staticInit
                    : 'static' 'init' '(' ')'
                    '{'
                    expressionOrDeclarations?
                    '}'
                    ;
%s
  @Mode: compileonly
  @Negative: yes
  @Structure: single
  @CompileWarning: no
  @Comment: Auto-generated by gen.py
  @Issue: %s6136
*/

%s {
    %s
}

main() { }
'''
desc = '  @Description: Checks that %s is not permitted.'

counter = 2
def write_counted(contents : str):
  global counter
  with open(path.format(str(counter).zfill(3)), 'w') as file:
    file.write(contents)
    counter += 1

static_init = '''static init() {
        %s
    }'''

def params(test_case):
  ret = {
    'issue' : ''
  }
  if len(test_case) < 3:
    return ret
  ret.update(test_case[2])
  return ret

def wrap(s: str):
  return '\n'.join(textwrap.wrap(s, 119, subsequent_indent='                ', replace_whitespace=False))

modifiers = ['public', 'private', 'protected', 'static']
test_cases = [
  ('using `init static` in a {t}', 'init static() { }'),
  ('using `staticinit` as one word in a {t}', 'staticinit() { }'),
  ('using `static init init` in a {t}', 'static init init() { }'),
  ('using `static` with a primary constructor of a {t}', 'static {name}() { }'),
  ('having arguments in the {t} static initializer', 'static init(x : Int64) { }'),
  ('using function body before `static` in a {t}', '{ } static init()'),
  ('{t} static initializer with "" instead of ()', 'static init"" { }'),
  ('{t} static initializer without curly brackets', 'static init()'),
  ('{t} static initializer without an opening curly bracket', 'static init() }'),
  ('{t} static initializer without a closing curly bracket', 'static init() {'),
  ('{t} static initializer without an opening parenthesis', 'static init) { }'),
  ('{t} static initializer without a closing parenthesis', 'static init( { }'),
  ('{t} static initializer with two bodies', 'static init() { } { }'),
  ('{t} static initializer with two parameters lists', 'static init()() { }'),
  ('class definition inside the {t} static initializer', static_init % 'class Class { }'),
  ('struct definition inside the {t} static initializer', static_init % 'struct Struct { }'),
  ('interface definition inside the {t} static initializer', static_init % 'interface Interface { }'),
  ('enum definition inside the {t} static initializer', static_init % '''enum E {
            E0
        }'''),
  ('type alias definition inside the {t} static initializer', static_init % 'type IntAlias = Int64'),
  ('import inside the {t} static initializer', static_init % 'from std import math.*'),
  ('package definition inside the {t} static initializer', static_init % 'package p'),
  *[(f'{mod} {mut[0]} member variable definition inside the {{t}} static initializer', static_init % f'{mod} {mut[1]} v = 1')
    for mod in modifiers for mut in [('mutable', 'var'), ('immutable', 'let')]],
  *[(f'{mod} function definition inside the {{t}} static initializer', static_init % f'{mod} func f {{ }}')
    for mod in modifiers],
  ('immutable property definition inside the {t} static initializer', static_init % '''prop p : Int64 {
            get {
                1
            }
        }''', {'issue' : '6124, '}),
  ('mutable property definition inside the {t} static initializer', static_init % '''mut prop p : Int64 {
            get {
                1
            }
            set(v) { }
        }''', {'issue' : '6124, '}),
  ('init constructor inside the {t} static initializer', static_init % 'init() { }'),
  ('primary constructor inside the {t} static initializer', static_init % '{name}() { }'),
  ('finalizer inside the {t} static initializer', static_init % '~init() { }'),
  ('another static initializer inside the {t} static initializer', static_init % 'static init() { }'),
]


type_info = [(t[:t.rindex(' ')], t, t[t.rindex(' ') + 1:t.rindex(' ') + 2])
             for t in ['class C', 'abstract class A', 'class G<T>', 'struct S']]
tests = [template % (wrap(desc % tc[0].format(t=ti[0])), params(tc)['issue'], ti[1], str(tc[1]).replace('{name}', ti[2]))
         for tc in test_cases for ti in type_info]
for test in tests:
  write_counted(test)
